﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using DataAccess;
using Common;
using Common.Views;

namespace BL_WServices
{
    /// <summary>
    /// This is the WCF Service which is implementing the interface IOrdersService
    /// </summary>
    public class OrdersService : IOrdersService
    {
        /// <summary>
        ///  This will place an order for the client.
        ///  It will add the list of products, username, and orderID.
        ///  It will add the products, quantity, date of purchase and the username who bought the products.
        /// </summary>
        /// <param name="username">Of type string. The username who bought the products.</param>
        /// <param name="oID">Of type Guid. Used to enter a new OrderID of type guid</param>
        /// <param name="products">Of type List. List of products that will be placed in the order.</param>
        public void AddOrder(string username, Guid oID, List<CartView> products)
        {
            OrdersRepository or = new OrdersRepository(false);
            ProductsRepository pr = new ProductsRepository(false);
            or.Entity = pr.Entity;

            Order o = new Order();
	        o.OrderID = oID;
            o.DatePurchased = DateTime.Now;
            o.Username = username;

            OrderDetail od;

            try
            {
                or.Entity.Connection.Open();
                or.Transaction = pr.Transaction = or.Entity.Connection.BeginTransaction();

                or.AddOrder(o);

                foreach (CartView cv in products)
                {
                    od = new OrderDetail();
                    od.OrderID = oID;
                    od.ProductID = cv.ProductID;
                    od.ProductQty = cv.Quantity;
                    DateTime wed = DateTime.Now;
                    od.WarrantyExpiryDate = wed.AddYears(+2);

                    or.AddOrderDetails(od);
                    pr.DecreaseStock(cv.ProductID, cv.Quantity);
                }

                foreach (Cart c in pr.GetShoppingCartByUsername(username))
                {
                    pr.RemoveShoppingCart(c);
                }
                or.Transaction.Commit();
            }
            catch (Exception ex)
            {
                or.Transaction.Rollback();
                throw new Exception("An error has occurred. Please try again later");
            }
            finally
            {
                or.Entity.Connection.Close();
            }
        }

        /// <summary>
        /// Returns the list of products bought by a particular user
        /// </summary>
        /// <param name="username">Of type string. Used to get the list of products by username</param>
        /// <returns>Returns the list of products</returns>
        public IQueryable<OrdersView> GetProductsBoughtByUser(string username)
        {
            return new OrdersRepository().GetProductsBoughtByUser(username);
        }

        /// <summary>
        /// This method is used to get the most purchased item from the database
        /// </summary>
        /// <returns>Returns the product which has been most purchased</returns>
        public IQueryable<StatisticalView> MostPurchasedItem()
        {
            return new OrdersRepository().MostPurchasedItem();
        }

        /// <summary>
        /// This method is used to get the most highly rated item from the database
        /// </summary>
        /// <returns>Returns the product which has been most highly rated</returns>
        public IQueryable<StatisticalView> HighlyRatedItem()
        {
            return new OrdersRepository().HighlyRatedItem();
        }

        /// <summary>
        /// This method is used to get the highest number of faults for 10 products
        /// </summary>
        /// <returns>Returns 10 products which have the highest number of faults</returns>
        public IQueryable<StatisticalView> HighestNumOfFaults()
        {
            return new OrdersRepository().HighestNumOfFaults();
        }

        /// <summary>
        /// This method is used to get the lowest number of faults for 10 products
        /// </summary>
        /// <returns>Returns products which have the lowest number of faults</returns>
        public IQueryable<StatisticalView> LeastNumOfFaults()
        {
            return new OrdersRepository().LeastNumOfFaults();
        }

        /// <summary>
        /// Save the View Items Purchased Details by username
        /// </summary>
        /// <param name="username">Of type string. Used to save the details according to username</param>
        public void SaveDetails(string username)
        {
            new OrdersRepository().SaveDetails(username);
        }
    }
}
